<template>
  <a-row>
    <a-col :span="6">
      <a-card :style="{height: height, overflow: 'auto'}">
        <a-tree
          :showLine="true"
          :tree-data="data"
          @select="onSelect"
          :selectedKeys="selectedKeys"
          :expandedKeys.sync="expandedKeys"
          draggable
          @dragenter="onDragEnter"
          @drop="onDrop"
        >
          <template slot="title" slot-scope="record">
            <span>{{record.title}}</span>
            <ych-icon type="plus" style="margin-left: 10px;" @click="addChildren(record)"/>
            <a-popconfirm :title="$t('m.common.tip.delete_confirm')" @confirm="() => removeItem(record)">
              <ych-icon type="delete" style="margin-left: 10px;"/>
            </a-popconfirm>
            <ych-icon type="copy" style="margin-left: 10px;" @click="copyItem(record)"/>
          </template>
        </a-tree>
      </a-card>
    </a-col>
    <a-col :span="18">
      <a-card :style="{height: height, overflow: 'auto'}">
        <TreeNodeDetail v-if="selectedData" :form="selectedData" :groupId="groupId" :parentCols="parentCols"
                        :model="model"/>
      </a-card>
    </a-col>
  </a-row>
</template>

<script>

  import { randomNumber } from '@/utils/util'
  import TreeNodeDetail from './TreeNodeDetail'

  export default {
    name: 'TreeDesigner',
    components: {
      TreeNodeDetail
    },
    props: {
      layout: {
        type: String,
        required: false
      },
      groupId: {
        type: String,
        required: true
      },
      model: {
        type: Object,
        required: false,
        default: () => {
        }
      },
    },
    data () {
      return {
        data: [],
        parentData: null,
        parentCols: [],
        selectedData: null,
        selectedKeys: [],
        expandedKeys: [],
        height: document.body.clientHeight - 53 - 235 + 'px',
      }
    },
    methods: {
      setData (value) {
        const json = value ? JSON.parse(value) : {}
        if ('2' != json.type) {
          return
        }
        const data = json.data ? json.data : []
        if (data.length == 0) {
          data.push({
            key: 'node_' + randomNumber(6),
            title: this.$t('m.eform.formDesign.label.gen-jie-dian'),
            sql: '',
            keyName: '',
            titleName: '',
            level: 0,
            tableName: '',
            cycle: false,
            selection: false,
            cols: [],
            children: []
          })
        }
        this.setTreeNodeSlots(data)
        this.data = data
        this.selectedKeys = [this.data[0].key]
      },
      setTreeNodeSlots (data) {
        data.forEach(item => {
          if (item.children && item.children.length > 0) {
            this.setTreeNodeSlots(item.children)
          }
          item['scopedSlots'] = { title: 'title' }
        })
      },
      getData (formData) {
        const selectionData = this.getSelection(this.data)
        formData.treeData = JSON.stringify({
          type: '2',
          data: this.data
        })
        formData.viewSql = this.getViewSql(selectionData)
        formData.actAppViewColList = this.getColList(selectionData)
        formData.tableName = selectionData ? selectionData.tableName : ''
      },
      getViewSql (selectionData) {
        if (selectionData && selectionData.tableName) {
          const sql = 'select ' + selectionData.keyName + ', ' + selectionData.titleName + ' from ' + selectionData.tableName
          return sql
        } else {
          return ''
        }
      },
      getColList (selectionData) {
        const dataSource = []
        if (selectionData && selectionData.keyName) {
          dataSource.push(this.createColData(selectionData.keyName, selectionData.cols || [], 1))
        }
        if (selectionData && selectionData.titleName) {
          dataSource.push(this.createColData(selectionData.titleName, selectionData.cols || [], 2))
        }
        return dataSource
      },
      getSelection (data) {
        for (let i = 0; i < data.length; i++) {
          if (data[i].selection) {
            return data[i]
          }
          if (data[i].children) {
            const sub = this.getSelection(data[i].children)
            if (sub) {
              return sub
            }
          }
        }
      },
      createColData (key, cols, orderNum) {
        let timestamp = new Date().getTime()
        let id = '' + timestamp + randomNumber(6)
        const colOption = cols.find(vo => vo.key == key)
        const data = {
          id: id,
          colCode: key,
          colName: colOption ? colOption.title : key,
          colType: 'varchar',
          orderNum: orderNum
        }
        return data
      },
      onSelect (selectedKeys, info) {
        if (selectedKeys.length == 0) {
          return
        }
        this.selectedKeys = selectedKeys
      },
      getSelectedData (data, key, parent) {
        for (let i = 0; i < data.length; i++) {
          if (data[i].key == key) {
            this.parentData = parent
            return data[i]
          }
          if (data[i].children && data[i].children.length > 0) {
            let sub = this.getSelectedData(data[i].children, key, data[i])
            if (sub) {
              return sub
            }
          }
        }
      },
      addChildren (record) {
        const currentNode = this.getSelectedData(this.data, record.key)
        currentNode.children = [...currentNode.children, {
          key: 'node_' + randomNumber(6),
          title: this.$t('m.eform.formDesign.label.xin-jie-dian'),
          sql: '',
          keyName: '',
          titleName: '',
          tableName: '',
          cycle: false,
          selection: false,
          cols: [],
          children: [],
          scopedSlots: { title: 'title' }
        }]
        if (this.expandedKeys.indexOf(record.key) == -1) {
          this.expandedKeys.push(record.key)
        }
      },
      removeItem (record) {
        if (this.data.length == 1 && this.data[0].key == record.key) {
          this.messageUtil.warning(this.$t('m.eform.formDesign.label.bu-neng-shan-chu-zui-hou-yi-ge-gen-jie-dian'))
          return
        }
        this.removeSelectedData(this.data, record.key)
        this.selectedKeys = [...this.selectedKeys]
      },
      copyItem (record) {
        const currentNode = this.getSelectedData(this.data, record.key)
        const copyNode = JSON.parse(JSON.stringify(currentNode))
        copyNode.children = []
        copyNode.key = 'node_' + randomNumber(6)
        copyNode.title = copyNode.title + '_new'
        if (this.parentData) {
          const children = this.parentData.children
          this.parentData.children = [...children, copyNode]
        } else {
          const children = this.data
          this.data = [...children, copyNode]
        }
      },
      removeSelectedData (data, key) {
        let index = -1
        for (let i = 0; i < data.length; i++) {
          if (data[i].key == key) {
            index = i
            break
          }
          if (data[i].children && data[i].children.length > 0) {
            let sub = this.removeSelectedData(data[i].children, key)
            if (sub) {
              return sub
            }
          }
        }
        if (index != -1) {
          data.splice(index, 1)
          return true
        }
      },
      onDragEnter (info) {
      },
      onDrop (info) {
        const dropKey = info.node.eventKey
        const dragKey = info.dragNode.eventKey
        const dropPos = info.node.pos.split('-')
        const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1])
        const loop = (data, key, callback) => {
          data.forEach((item, index, arr) => {
            if (item.key === key) {
              return callback(item, index, arr)
            }
            if (item.children) {
              return loop(item.children, key, callback)
            }
          })
        }
        const data = [...this.data]

        // Find dragObject
        let dragObj
        loop(data, dragKey, (item, index, arr) => {
          arr.splice(index, 1)
          dragObj = item
        })
        if (!info.dropToGap) {
          // Drop on the content
          loop(data, dropKey, item => {
            item.children = item.children || []
            // where to insert 示例添加到尾部，可以是随意位置
            item.children.push(dragObj)
          })
        } else if (
          (info.node.children || []).length > 0 && // Has children
          info.node.expanded && // Is expanded
          dropPosition === 1 // On the bottom gap
        ) {
          loop(data, dropKey, item => {
            item.children = item.children || []
            // where to insert 示例添加到尾部，可以是随意位置
            item.children.unshift(dragObj)
          })
        } else {
          let ar
          let i
          loop(data, dropKey, (item, index, arr) => {
            ar = arr
            i = index
          })
          if (dropPosition === -1) {
            ar.splice(i, 0, dragObj)
          } else {
            ar.splice(i + 1, 0, dragObj)
          }
        }
        this.data = data
        this.selectNode()
      },
      selectNode () {
        this.parentData = null
        if (this.selectedKeys && this.selectedKeys.length > 0) {
          this.selectedData = this.getSelectedData(this.data, this.selectedKeys[0])
        } else {
          this.selectedData = null
        }
        this.parentCols = this.parentData ? this.parentData.cols : []
      },
    },
    watch: {
      layout: {
        handler (value) {
          this.setData(value)
        },
        immediate: true
      },
      selectedKeys: {
        handler () {
          this.selectNode()
        },
        immediate: true
      },
    }
  }
</script>
